<template>
  <div id="board">
    <!--头部-->
    <Header></Header>

    <!--正文-->
    <main>
      <h2 v-if="board">
        {{ board[0].name }}
        <span class="btn btn-icon">邀请</span>
      </h2>

      <!--面板容器-->
      <div class="board">
        <!--面板列表容器-->
        <List
          v-for="item of lists"
          :key="item.id"
          :data="item"
          @dragStart="dragStart"
          @dragMove="dragMove"
          @dragEnd="dragEnd"
        ></List>

        <!--无内容列表容器-->
        <div
          :class="
            listAdding
              ? `list-wrap no-content list-adding`
              : `list-wrap no-content`
          "
        >
          <!-- 一开始显示的状态 -->
          <div class="list-add" @click="showListAddingn">
            <span class="icon icon-add"></span>
            <span>添加另一个列表</span>
          </div>

          <!-- 进入编辑状态 -->
          <div class="list">
            <div class="list-cards">
              <div class="list-card-add-form">
                <input
                  ref="newCardAdd"
                  v-model.lazy="inputListName"
                  class="form-field-input"
                  placeholder="为这张卡片添加标题……"
                />
              </div>
            </div>

            <!-- 编辑状态时的底部 -->
            <div class="list-footer">
              <div class="list-add-confirm">
                <button class="btn btn-success" @click="submitAddNewList">
                  添加列表
                </button>
                <span class="icon icon-close" @click="closeListAdding"></span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </main>

    <PopUp></PopUp>

    <!-- 弹出的遮罩层 -->
    <router-view></router-view>
  </div>
</template>

<script>
import Header from "@/components/Header/header";
import PopUp from "@/components/PopUp/popup";
import List from "@/components/List/list";

export default {
  name: "Board",
  components: { Header, PopUp, List },

  created() {
    //  如果不是从主页进去的，而是在对应的board面板刷新或者直接输入url，那么拿不到数据
    //  这时候就要判断一下board属性是否存在，没有的话就手动拉取
    if (!this.board) {
      this.$store.dispatch("board/getBoard", this.$route.params.id);
    }
    if (this.lists.length === 0) {
      this.$store.dispatch("list/getLists", this.$route.params.id);
    }
  },

  computed: {
    board() {
      return this.$store.getters["board/getterBoard"](this.$route.params.id);
    },
    lists() {
      return this.$store.getters["list/getterLists"](this.$route.params.id);
    },
  },

  data() {
    return {
      listAdding: false,
      inputListName: "",
    };
  },

  methods: {
    //  显示添加面板
    showListAddingn() {
      this.listAdding = true;

      this.$nextTick(() => {
        this.$refs.newCardAdd.focus();
      });
    },

    //  关闭添加面板
    closeListAdding() {
      this.listAdding = false;
    },

    //  提交添加新的列表
    submitAddNewList() {
      if (this.inputListName.trim() === "") {
        this.$refs.newCardAdd.focus();
      } else {
        try {
          this.$store.dispatch("list/postList", {
            boardId: parseInt(this.$route.params.id),
            name: this.inputListName,
          });
          this.$message.success("提交成功");
          this.listAdding = false;
        } catch (error) {
          console.log(error);
        }
      }
    },

    //  拖拽相关
    //  拖拽交换位置之后，使用querySelectorAll，以及修改其内部的排序order

    dragStart(e) {
      let el = e.component.$el;
      let board = el.parentNode;
      let lists = [...board.querySelectorAll(".list-wrap")];

      //  用来记录拖拽之前的位置,
      el._index = lists.indexOf(el);
    },

    //  e 是 List 传过来的参数, e: {component:VueComponent, x, y}
    dragMove(e) {
      //  el 代表现在拖拽的元素
      let el = e.component.$el;
      //  当前面板元素
      let board = el.parentNode;
      let lists = [...board.querySelectorAll(".list-wrap")];
      let currIndex = lists.indexOf(el);

      lists.forEach((list, index) => {
        if (index !== currIndex) {
          let clientRect = list.getBoundingClientRect();

          //  如果鼠标进入了其他列表的范围内
          if (
            e.x >= clientRect.left &&
            e.x <= clientRect.right &&
            e.y >= clientRect.top &&
            e.y <= clientRect.bottom
          ) {
            //  如果拖拽到后面的列表，那么就插入到目标列表的下一个节点之前
            if (currIndex < index) {
              board.insertBefore(el, list.nextElementSibling);
            } else {
              //  如果拖拽到前面的列表，那么就插入到目标列表的位置之前
              board.insertBefore(el, list);
            }
          }
        }
      });
    },

    async dragEnd(e) {
      let el = e.component.$el;
      let board = el.parentNode;
      let lists = [...board.querySelectorAll(".list-wrap")];

      let currIndex = lists.indexOf(el);

      //  判断当前元素是否移动了，还是就拽了一下没换位置
      if (el._index !== currIndex) {
        //  获取当前所在位置的上一个列表和下一个列表的order值
        let prevOrder =
          lists[currIndex - 1] &&
          parseFloat(lists[currIndex - 1].dataset.order);
        //  dataset是html5的自定义属性，元素中 data-xxx 添加非标准属性
        //  然后通过ref.dataset.xxx 获得
        let nextOrder =
          lists[currIndex + 1] &&
          parseFloat(lists[currIndex + 1].dataset.order);

        //  这时候会有三种情况
        //  拖拽到最前面，prevOrder = undefined
        //  拖拽到最后面 nextOrder = NaN
        //  中间

        let newOrder;

        if (currIndex === 0) {
          newOrder = nextOrder / 2;
        } else if (currIndex === lists.length - 2) {
          //  为什么-2, 因为lists 包含了一个.list-wrap no-content...
          //  所以末尾会多一个出来
          newOrder = prevOrder + 65535;
        } else {
          newOrder = prevOrder + (nextOrder - prevOrder) / 2;
        }

        await this.$store.dispatch("list/editList", {
          boardId: parseInt(e.component.data.boardId),
          id: e.component.data.id,
          name: e.component.data.name,
          order: newOrder,
        });
      }
    },
  },
};
</script>

<style></style>
